package live

import (
	"errors"
	"fmt"
	"github.com/gorilla/websocket"
	"io/ioutil"
	"math/rand"
	"net/http"
	"regexp"
	"strconv"
	"strings"
)

type DyLive interface {
	Start() interface{}
}

type defaultDyLive struct {
	ttwid     string
	roomId    string
	liveId    string
	liveUrl   string
	userAgent string
}

func NewDyLive(liveId string) DyLive {
	return &defaultDyLive{
		ttwid:     "",
		roomId:    "",
		liveId:    liveId,
		liveUrl:   "https://live.douyin.com/",
		userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36",
	}
}

func getAllLetters() []string {
	var letters []string
	for char := 'a'; char <= 'z'; char++ {
		letters = append(letters, string(char))
	}
	for char := 'A'; char <= 'Z'; char++ {
		letters = append(letters, string(char))
	}
	for num := 0; num <= 9; num++ {
		letters = append(letters, strconv.Itoa(num))
	}
	return letters
}

func (d *defaultDyLive) getMsToken() string {
	length := 107

	randomStr := ""
	baseStr := strings.Join(getAllLetters(), "") + "=_"
	baseStrLen := len(baseStr)
	for i := 0; i < length; i++ {
		randomStr += string(baseStr[rand.Intn(baseStrLen)])
	}
	return randomStr
}

func (d *defaultDyLive) getTtwid() (string, error) {
	// TODO 调试
	return "1%7CdLD4bp4vdZMQ5FB5N8cINAJLPEtdgoVcKcI7NjDu7as%7C1718268328%7C3d8800906fb7896330b8ebd02a4e408e011f490e24ef62bcbb54a20d4debceec", nil

	if d.ttwid != "" {
		return d.ttwid, nil
	}

	request, err := http.NewRequest("GET", d.liveUrl, nil)
	if err != nil {
		return "", err
	}
	request.Header.Add("User-Agent", d.userAgent)

	//client := &http.Client{
	//	Transport: &http.Transport{
	//		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	//	},
	//	Timeout: time.Duration(10) * time.Second,
	//}

	resp, err := new(http.Client).Do(request)
	if err != nil {
		return "", err
	}

	var ttwid string

	for _, cookie := range resp.Cookies() {
		if cookie.Name == "ttwid" {
			ttwid = cookie.Value
			break
		}
	}

	if ttwid == "" {
		return "", errors.New("ttwid is empty string")
	}
	return ttwid, nil
}

func (d *defaultDyLive) getRoomId() (string, error) {
	// TODO 调试
	return "7374655630008666917", nil

	if d.roomId != "" {
		return d.roomId, nil
	}

	msToken := d.getMsToken()

	url := d.liveUrl + d.liveId

	request, err := http.NewRequest("GET", url, nil)
	if err != nil {
		return "", err
	}

	request.Header.Add("User-Agent", d.userAgent)
	request.Header.Add("cookie", "ttwid="+d.ttwid+"&msToken="+msToken+"; __ac_nonce=0123407cc00a9e438deb4")

	resp, err := new(http.Client).Do(request)
	if err != nil {
		return "", err
	}

	contents, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}

	regex := regexp.MustCompile(`roomId\\":\\"(\d+)\\"`)

	matches := regex.FindStringSubmatch(string(contents))
	if len(matches) < 2 {
		return "", errors.New("no matching roomId was found")
	}
	return matches[1], nil
}

// Start 开始监听直播间消息
func (d *defaultDyLive) Start() interface{} {
	fmt.Println("start...")

	var err error

	if d.ttwid, err = d.getTtwid(); err != nil {
		panic(err)
	}
	fmt.Println("ttwid: ", d.ttwid)

	if d.roomId, err = d.getRoomId(); err != nil {
		panic(err)
	}
	fmt.Println("roomId: ", d.roomId)

	wss := "wss://webcast3-ws-web-lq.douyin.com/webcast/im/push/v2/?" +
		"app_name=douyin_web&version_code=180800&webcast_sdk_version=1.3.0&update_version_code=1.3.0" +
		"&compress=gzip" +
		"&internal_ext=internal_src:dim|wss_push_room_id:" + d.roomId + "|wss_push_did:" + d.roomId +
		"|dim_log_id:202302171547011A160A7BAA76660E13ED|fetch_time:1676620021641|seq:1|wss_info:0-1676" +
		"620021641-0-0|wrds_kvs:WebcastRoomStatsMessage-1676620020691146024_WebcastRoomRankMessage-167661" +
		"9972726895075_AudienceGiftSyncData-1676619980834317696_HighlightContainerSyncData-2&cursor=t-1676" +
		"620021641_r-1_d-1_u-1_h-1" +
		"&host=https://live.douyin.com&aid=6383&live_id=1" +
		"&did_rule=3&debug=false&endpoint=live_pc&support_wrds=1&" +
		"im_path=/webcast/im/fetch/&user_unique_id=" + d.roomId + "&" +
		"device_platform=web&cookie_enabled=true&screen_width=1440&screen_height=900&browser_language=zh&" +
		"browser_platform=MacIntel&browser_name=Mozilla&" +
		"browser_version=5.0%20(Macintosh;%20Intel%20Mac%20OS%20X%2010_15_7)%20AppleWebKit/537.36%20(KHTML,%20" +
		"like%20Gecko)%20Chrome/110.0.0.0%20Safari/537.36&" +
		"browser_online=true&tz_name=Asia/Shanghai&identity=audience&" +
		"room_id=" + d.roomId + "&heartbeatDuration=0&signature=00000000"

	headers := http.Header{
		"Cookie": []string{fmt.Sprintf("ttwid=%s", d.ttwid)},
		"user-agent": []string{
			"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)",
		},
	}

	ws, _, err := websocket.DefaultDialer.Dial(wss, headers)
	if err != nil {
		panic(err)
	}
	defer func() { _ = ws.Close() }()

	for {
		_, message, err := ws.ReadMessage()
		if err != nil {
			panic(err)
		}

		if message != nil {
			fmt.Println(message)
		}
	}

	return nil
}
